//
//  FPluginHost.m
//  Foundation
//
//  Created by 新庭 on 2019/7/8.
//

#import "FPluginHost.h"
#import "FPluginFake.h"
#import <objc/runtime.h>
#import "FPluginCenter.h"
#import "FPluginFakeArray.h"

#import "FPluginTableViewHost.h"
#import "NSObject+FPlugin.h"
#import "FPluginStore.h"

@interface FPluginHost ()

#pragma mark - Inner

@end

@implementation FPluginHost

- (instancetype)initWithHost:(NSString *)hIdentifier {
    return [self initWithHost:hIdentifier andPlugins:[FPluginCenter.sharedInstance loadPluginFor:hIdentifier]];
}

- (instancetype)initWithHost:(NSString *)hIdentifier andPlugins:(NSArray<id<FPlugin>> *)plugins {
    if (self = [super init]) {
        _hostIdentifier = hIdentifier;
        _plugins = plugins;
        
        if (self.pluginPriority.count > 0) {
            self.pluginPriority = self.pluginPriority;
        }
        
        [FPluginCenter.sharedInstance.pluginStore.hosts addPointer:(__bridge void *)self];
    }
    return self;
}

- (void)reloadWithHost:(NSString *)hIdentifier {
    _hostIdentifier = hIdentifier;
    _plugins = [FPluginCenter.sharedInstance loadPluginFor:hIdentifier];
    if (self.pluginPriority.count > 0) {
        self.pluginPriority = self.pluginPriority;
    }
}

- (NSUInteger)loadPlugins:(FPluginArg *)arg {
    _context = arg.context;
    
    if (!self.hostProxy) {
        self.hostProxy = [arg.collectable proxyFor:arg];
    }
    
    __block NSUInteger loaded = 0;
    NSMutableArray<id<FPlugin>> *mArr = [NSMutableArray array];
    [self.plugins enumerateObjectsUsingBlock:^(id<FPlugin>  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        FPluginArg *argCp = [arg copy];
        [self.hostProxy prepareArg:argCp forPlugin:obj];
        
        if ([obj plg_load:argCp]) {
            loaded++;
        } else {
            [mArr addObject:obj];
        }
    }];
    
    [mArr enumerateObjectsUsingBlock:^(id<FPlugin>  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [obj plg_unLoad];
    }];
    NSMutableArray *mPlugins = [NSMutableArray arrayWithArray:self.plugins];
    [mPlugins removeObjectsInArray:mArr];
    _plugins = mPlugins;
    return loaded;
}

- (void)refreshPlugins:(FPluginArg *)arg {
    arg.context = self.context;
    
    [self.plugins enumerateObjectsUsingBlock:^(id<FPlugin>  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        FPluginArg *argCp = [arg copy];
        [self.hostProxy prepareArg:argCp forPlugin:obj];
        
        [obj plg_refresh:argCp];
    }];
}

- (void)unloadPlugins {
    [self.plugins enumerateObjectsUsingBlock:^(id<FPlugin>  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [obj plg_unLoad];
    }];
}

- (void)setPluginPriority:(NSArray<NSString *> *)pluginPriority {
    _pluginPriority = pluginPriority;
    
    if (self.plugins.count == 0) {
        return;
    }
    
    NSMutableArray *mArr = [NSMutableArray array];
    NSMutableArray *mOriArr = [NSMutableArray arrayWithArray:self.plugins];
    
    for (NSString *plgid in pluginPriority) {
        NSInteger index = [mOriArr indexOfObjectPassingTest:^BOOL(id<FPlugin>  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            return [[obj.class identifier] isEqualToString:plgid];
        }];
        if (index != NSNotFound) {
            id<FPlugin> plg = [mOriArr objectAtIndex:index];
            [mArr addObject:plg];
            [mOriArr removeObjectAtIndex:index];
        }
    }
    // 剩余的直接添加
    [mArr addObjectsFromArray:mOriArr];
    
    _plugins = mArr;
}

@synthesize datas = _datas;
- (NSMutableArray *)datas {
    if (!_datas) {
        _datas = (NSMutableArray *)[FPluginFakeArray fakeFor:[NSMutableArray array]];
    }
    return _datas;
}

#pragma mark - Private


@end
